

#include "Encoder.h"

Encoder::Encoder(int parNumClusters){
	numClusters = parNumClusters;
}

Encoder::~Encoder(){

}

void Encoder::addEntry(int type, boost::unordered_map<std::string, std::vector<Type> > parMap){
	boost::unordered_map<std::string, IntervalSelector> intervalMap;
	for (boost::unordered_map<std::string, std::vector<Type> >::iterator it=parMap.begin(); it!=parMap.end(); it++){
		std::string attributeName = it->first;
		std::vector<Type> listValues = it->second;
//		cout << "type " << type << ": " << attributeName << ": " << listValues.size() << endl;
		cout << "type " << type << ": " << attributeName << ": ";

		std::sort(listValues.begin(), listValues.end(), util::compare);

		for (int iter=0; iter<listValues.size(); iter++){
//			cout << listValues[iter].intVal << " ";
		}
//		cout << endl;
		int step = listValues.size() / numClusters;
		int overflow = listValues.size() % numClusters;
//		cout << "clusters: " << numClusters << endl;
//		cout << "step: " << step << endl;
//		cout << "overflow: " << overflow << endl;
		Type pointList[numClusters-1];
//		cout << "point: ";

		int index;
		if (overflow>0) {
			index = step;
			overflow--;
		}
		else index = step -1;
		for (int i=0; i<numClusters-1; i++) {
			pointList[i] = listValues[index];
//			cout  << pointList[i].intVal << " ";
			if (overflow>0) {
				index += step +1;
				overflow--;
			}
			else index += step;
		}
//		cout << endl;
		IntervalSelector intSelector = IntervalSelector(attributeName, pointList, numClusters-1);
//		cout << "Interval Selector creato" << endl;
		intervalMap.insert(make_pair(attributeName, intSelector));
		cout << endl;
	}
	attributeMap.insert(make_pair(type, intervalMap));
}


std::string Encoder::encode(PubPkt* pkt){

	std::string encodedString;

	int type = pkt->getEventType();
	encodedString = util::intToString(type);

	boost::unordered_map<int, boost::unordered_map<std::string, IntervalSelector > >::iterator it = attributeMap.find(type);
	for (int i=0; i<pkt->getAttributesNum(); i++){
		Attribute attribute = pkt->getAttribute(i);
		std::string attributeName = attribute.name;
		if (attribute.type == BOOL) {
			encodedString += "_";
			encodedString += util::boolToCharString(attribute.boolVal);
			continue;
		}
		if (attribute.type == STRING){
			encodedString += "_";
			encodedString += attribute.stringVal;
			continue;
		}
		if (it!=attributeMap.end()){
			boost::unordered_map<std::string, IntervalSelector >::iterator it2 = it->second.find(attributeName);
			if (it2 != it->second.end()){
				encodedString += "_" + it2->second.getMatchingIntervals(attribute);
			}
		}
	}
	return encodedString;
}


std::set<std::string> Encoder::encode(BackSubPkt* pkt){

	std::set<std::string> encodedStrings;

	int type = pkt->getEventType();
	std::string typeString = util::intToString(type);
	encodedStrings.insert(typeString);

	boost::unordered_map<int, boost::unordered_map<std::string, IntervalSelector > >::iterator it = attributeMap.find(type);
	//if (it!=attributeMap.end()) //cout << "e fin qui ok!" << endl;

	for (int i=0; i<pkt->getConstraintsNum(); i++){
		std::set<std::string> updatedEncodedStrings;
		Constraint constraint = pkt->getConstraint(i);
		std::string constraintName = constraint.name;

		if (constraint.type == BOOL) {
			for (std::set<std::string>::iterator it3 = encodedStrings.begin(); it3!=encodedStrings.end(); it3++){
				std::string currentString = *it3;
				currentString += "_";
				currentString += util::boolToString(constraint.boolVal);
				updatedEncodedStrings.insert(currentString);
			}
			encodedStrings = updatedEncodedStrings;
			continue;
		}
		if (constraint.type == STRING) {
			for (std::set<std::string>::iterator it3 = encodedStrings.begin(); it3!=encodedStrings.end(); it3++){
				std::string currentString = *it3;
				currentString += "_";
				currentString += constraint.stringVal;
				updatedEncodedStrings.insert(currentString);
			}
			encodedStrings = updatedEncodedStrings;
			continue;
		}
		if (it!=attributeMap.end()){
			boost::unordered_map<std::string, IntervalSelector >::iterator it2 = it->second.find(constraintName);
			if (it2 != it->second.end()){
				std::set<std::string> matchedStringSet = it2->second.getMatchingIntervals(constraint);
				for (std::set<std::string>::iterator it3 = encodedStrings.begin(); it3!=encodedStrings.end(); it3++){
					std::string currentString = *it3;
					for (std::set<std::string>::iterator it4 = matchedStringSet.begin(); it4!=matchedStringSet.end(); it4++){
						std::string currentMatched = *it4;
						std::string newString = currentString;
						newString += "_";
						newString += currentMatched;
						updatedEncodedStrings.insert(newString);
					}
				}
			}
			encodedStrings = updatedEncodedStrings;
		}
	}
	return encodedStrings;
}

void Encoder::clear(){
	//cout << "encoder resettato" << endl;
	attributeMap.clear();


}
